home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 August / macformat-027.iso / mac / Shareware City / Developers / Oberon⁄F / Manuals / Overview (.txt) < prev    next >
Encoding:
Oberon Document  |  1994-06-07  |  46.0 KB  |  266 lines  |  [oODC/obnF]

  1. Documents.StdDocumentDesc
  2. Documents.DocumentDesc
  3. Containers.ViewDesc
  4. Views.ViewDesc
  5. Stores.StoreDesc
  6. Documents.ModelDesc
  7. Containers.ModelDesc
  8. Models.ModelDesc
  9. Stores.ElemDesc
  10. TextViews.StdViewDesc
  11. TextViews.ViewDesc
  12. TextModels.StdModelDesc
  13. TextModels.ModelDesc
  14. TextModels.AttributesDesc
  15. Geneva
  16. TextRulers.StdRulerDesc
  17. TextRulers.RulerDesc
  18. TextRulers.StdStyleDesc
  19. TextRulers.StyleDesc
  20. TextRulers.AttributesDesc
  21. Geneva
  22. Geneva
  23. Geneva
  24. Geneva
  25. HostPictures.StdViewDesc
  26. Geneva
  27. Controllers
  28. Dialog
  29. Views
  30. Models
  31. Stores
  32. Files
  33. Fonts
  34. Ports
  35. Domains
  36. Geneva
  37. Ports.Frame
  38. Views.Frame
  39. Views.RootFrame
  40. Stores.Store
  41. Controllers.Controller
  42. Views.View
  43. Stores.Alien
  44. Views.Alien
  45. Stores.Elem
  46. Models.Model
  47. Stores.AlienElem
  48. Geneva
  49. Controllers.Message
  50. Controllers.MarkMsg
  51. Controllers.PollFocusMsg
  52. Controllers.RequestMessage
  53. Controllers.PollSectionMsg
  54. Controllers.PollOpsMsg
  55. Controllers.ScrollMsg
  56. Controllers.TickMsg
  57. Controllers.SelectMsg
  58. Controllers.EditMsg
  59. Controllers.ReplaceViewMsg
  60. Models.Message
  61. Models.NeutralizeMsg
  62. Models.UpdateMsg
  63. Controllers.PageMsg
  64. Controllers.CursorMessage
  65. Controllers.PollCursorMsg
  66. Controllers.TrackMsg
  67. Controllers.TransferMessage
  68. Controllers.PollDropMsg
  69. Controllers.DropMsg
  70. Domains.Message
  71. Views.Message
  72. Views.NeutralizeMsg
  73. Views.NotifyMsg
  74. Dialog.Field
  75. Dialog.Array
  76. Dialog.Subrange
  77. Dialog.Enumeration
  78. Dialog.Color
  79. Dialog.Length
  80. Dialog.Size
  81. Dialog.Units
  82. Dialog.Weight
  83. Dialog.Time
  84. Dialog.Selection
  85. Dialog.Style
  86. Geneva
  87. RS232Rider
  88. RS232Rider
  89. RS232Carrier
  90. NetRider
  91. NetRider
  92. NetCarrier
  93. Geneva
  94.     BinMapper
  95. ASCIIMapper
  96. NetRider
  97. NetRider
  98. NetCarrier
  99. Geneva
  100. mapper
  101. rider
  102. Binary
  103. Mapper
  104. ASCII
  105. Mapper
  106. RS232Rider
  107. NetRider
  108. Binary
  109. on RS232
  110. ASCII
  111. on RS232
  112. Binary
  113. on net
  114. ASCII
  115. on net
  116. Geneva
  117. model
  118. controller
  119. controller
  120. Geneva
  121. window
  122. child window
  123.     text view
  124. text model
  125. graphic view
  126. frame for text view
  127. frame for (
  128. graphic view
  129. frame for (
  130. graphic view
  131. graphic model
  132. graphic view
  133. Geneva
  134. front path
  135. target path
  136. front focus
  137. target focus
  138. front window
  139. bottom window
  140. focus hierarchy
  141. Geneva
  142. model
  143. frame
  144. frame
  145. frame
  146. frame
  147. model notifies its
  148. views with a model
  149.     broadcast
  150. views notify their
  151. frames with view
  152. broadcasts
  153. 2 Overview
  154. 2.1 Module and Type Hierarchies
  155. Oberon/F is decomposed into a hierarchy of modules which provide systematically constructed abstractions. Features which are not used can be ignored. This makes it possible to start with an explanation of the core concepts (like in this section and in the tutorial part of this book), and later reveal further capabilities.
  156. Abstractions in Oberon/F are chosen such that they do not impose undue demands upon the underlying hardware. However, a bitmap display and a mouse are required, i.e. no attempt is made to achieve backward compatibility with character-oriented displays.
  157. At the "bottom" of Oberon/F, the differences between hardware platforms are hidden as much as possible. At the "top", the differences between user-interfaces are hidden as much as possible. For example, there are no assumptions built into Oberon/F about the underlying window system, e.g. whether it provides overlapping or tiling windows. In fact, the abstraction of a window is just as absent from Oberon/F as the abstraction of an application.
  158. Because Oberon/F constitutes a layer between the operating system and the application, it must be efficient. This not only applies to speed, but also to memory and disk requirements. However, the efficiency of a particular Oberon/F implementation is necessarily dependent on the quality of the underlying operating system and hardware.
  159. Oberon/F interfaces are safe, i.e. an Oberon/F application which doesn't use the low-level facilities of module SYSTEM is type-safe. A module which is type-safe may only create local damage, even if it contains arbitrary errors. In particular, it cannot destroy invariants guaranteed by other modules. This bug containment is especially relevant if objects of differing origins are combined in a single document.
  160. A central aspect of Oberon/F is its extensibility. It is possible to extend most major Oberon/F data types, in order to add new functionality to the existing system. Many basic services can be replaced or supplemented by new customized versions, in a way that existing applications can make use of the new facilities. To reach this degree of extensibility and configurability, module interfaces are constructed in a systematic way, which is described in this chapter.
  161. Picture 2.1a  Module Hierarchy of Oberon/F
  162. The diagram above shows the module structure of Oberon/F. A small labeled rectangle denotes a module. A module which (may) import another one is placed higher in the hierarchy. A large labeled rectangle denotes a complete subsystem, consisting of several related modules.
  163. The hierarchy is structured into a lower layer called core, and into an application layer. The core provides device drivers, the basic abstractions for storable objects, for editable objects, and for a hierarchical embedding of editable objects, i.e. for compound documents. The application layer provides three standard subsystems: a text subsystem, a subsystem for forms (e.g. dialog boxes), and a subsystem which constitutes the development environment. Miscellaneous other modules in the application layer are not shown here, e.g. various example modules.
  164. For each core module, a short description of its functionality is given:
  165. Module Domains defines a grouping construct for arbitrary objects. This construct is called a domain. As an example, every displayed document belongs to one domain. Most message broadcast are restricted to one domain.
  166. Module Files provides abstract files of a hierarchical file system, and readers and writers as access paths to files.
  167. Module Fonts handles font identification, font measurements, and font lookup.
  168. Module Stores defines the base type for all extensible storable objects, and file mappers for the externalization and internalization of stores.
  169. Module Ports provides abstract display ports, riders as access paths to ports, and frames as port mappers.
  170. Module Models defines a base type for the representation of storable data, as well as operations for the management of model modifications.
  171. Module Views defines the central abstraction of a view, which provides presentation of a model. 
  172. Module Controllers defines the abstraction of a controllers. A controller provides for user interaction with a view and the view's model.
  173. Module Dialog provides various facilities for the interaction with the user, e.g. standard dialogs for file opening and closing, and for presenting error messages.
  174. Modules which are not of general interest or do not provide portable abstractions are called private. Their interfaces may not be portable, may not be documented, or may change arbitrarily between Oberon/F releases. Most names of private modules start with the prefix "Host" or "Std", which are reserved subsystem prefixes. An implementation may contain further private global modules like Kernel, Modules, Reals, Windows, or Documents.
  175. Private modules are not shown in the above module diagram. Some of them may be described in the host-specific documentation for a given Oberon/F implementation, but should not be considered as parts of Oberon/F proper. This holds also for interface modules with the host platform, which may be provided as well, in order to allow direct access to features particular to the given platform.
  176. It is intended that some of the currently private modules, such as Kernel, Meta, Properties, Printers, Printing, Containers, and Documents will later be documented and become public.
  177. An Oberon/F developer can use his own unique module name prefix for the module names of his project(s), in order to eliminate name clashes with module names of other developers. Oberon microsystems acts as a clearinghouse for such name prefixes, by providing a prefix registration service (-> "Oberon/F, User's Guide").
  178. The module hierarchy gives an overview over the coarse structure of a software system, by showing the major abstractions and subsystems, and their import relations. On a finer level of granularity, it is helpful to consider the type hierarchies which are created through type extension. Typically, such type trees are drawn with the base type at the top, and with arrows downward to the extended types; i.e. quite unlike most natural trees, type trees have their roots at the top and grow downward. In Oberon/F, there is no need to have one common base type for all object types, thus we can draw a type forest (i.e. several type trees):
  179. Picture 2.1b  Hierarchies of Important Dynamic Object Types
  180. The above diagram shows all major type trees of dynamic Oberon/F objects. Interface types are drawn in boxes with thin outlines, concrete types are drawn in boxes with thicker outlines. The name of the object type, more precisely of its pointer type, is prefixed with the name of the module in which the object type is defined, e.g. Views.View denotes type View in module Views.
  181. The hierarchy of the most important static object types are shown in the diagram below:
  182. Picture 2.1c  Hierarchies of Important Static Object Types
  183. In this diagram, it can be seen that most important static objects in Oberon/F are message records.
  184. 2.2 Device Drivers: Carriers, Riders, Mappers, and Directories
  185. This chapter describes the strategy which is used for modeling device drivers, as well as data structures which can be accessed in a similar way as devices, e.g. texts.
  186. Access to a device's data passes through two different objects: a rider and a carrier. A carrier represents a data container, e.g. a file or a screen pixelmap. Several access paths may be open on one carrier at the same time. This n:1 relationship gives rise to the separation of carriers and riders, where a rider represents one access path to its carrier.
  187. The implementation of a rider must have intimate knowledge about the implementation of its carrier, e.g. a file rider must know about the disk sector corresponding to its current position. Thus an extension of a carrier usually requires an appropriate extension of its rider as well. As a consequence, a rider is generated by its carrier, which provides an allocation function for this purpose.
  188. Picture 2.2a  Carrier-Rider Separation showing N:1 Relationship
  189. A rider provides primitive input/output operations, the so-called bottleneck interface. These primitives can be used to build more complex operations which form a higher-level abstraction, possibly even an application-specific abstraction. Such a higher-level abstraction will generally be called a mapper in this documentation. A mapper contains a rider as a link to the carrier. During their use, mappers and riders form 1:1 relations, i.e. pairs.
  190. Picture 2.2b  Carrier-Rider-Mapper Separation
  191. In contrast to riders, mappers know nothing about a carrier's implementation, and thus can be extended independently. This independence means that every mapper may be used on any compatible rider, without the need to implement all combinations of mappers and riders individually. This situation is shown below for the case of riders that operate on serial carriers like RS232 links or networks:
  192. Picture 2.2c  Extensibility in two Dimensions
  193. As was explained in chapter 1.7 ("From White-Box Frameworks towards Black-Box Frameworks"), Oberon/F generally doesn't allow the extension of concrete types. Mappers are exceptions to this rule, because by their very nature they create or interpret fixed external representations, e.g. number formats on screen or the representation of binary data on a file. Apart from possible optimizations for efficiency reasons, this fixed external representation practically defines the complete behavior of a mapper. A procedure whose complete behavior is known may safely be extended (i.e. empty procedures, default procedures, mapper procedures, procedures whose source code is published). However, mappers and message records are the only exported concrete types in Oberon/F.
  194. Yet there must be a way to obtain objects of concrete types! For this purpose, a module which exports an interface type also provides a so-called directory object, accessible through a global variable. Such a directory provides functions to allocate new objects, and often also procedures for looking up objects by a given key (this property, although not always available, led to the generic term "directory"). For example, a file directory provides functions to create new empty files, as well as to look up existing files by name (a file directory object in Oberon/F does not, however, represent a single file subdirectory, but rather the whole file system).
  195. Directory objects are powerful facilities, since they can be replaced at run-time (usually this is done during the boot configuration process). This makes it possible to add and integrate extended services at run-time (i.e. new concrete types), which allows a system to grow in a controlled manner.
  196. To summarize:
  197. - Carrier    container for data
  198. - Rider    access path to carrier, bottleneck interface
  199. - Mapper    creates or interprets external data formats using a rider as link to a carrier
  200. - Directory    facility for generating or for looking up objects of concrete types
  201. 2.3 User Interaction: Models, Views, and Controllers
  202. Oberon/F supports storable objects, i.e. objects which can be stored to and loaded from non-volatile carriers. Such objects contain arbitrary persistent state (data stored in a non-volatile way, e.g. on disk). For this purpose, a type Store is provided, which is the base type of all storable types. Stores are externalized on and internalized from files. Module Stores provides readers and writers, which are file mappers that implement a binary encoding of Oberon/L values like characters, integers, sets, or of complete stores. A store uses these mappers to read or write its internal data, which possibly may contain other stores as well, i.e. stores can be embedded recursively.
  203. For interactive applications, three different extensions of stores are predefined by Oberon/F: models, views, and controllers. This seperation is known as the MVC paradigm, originally developed for Smalltalk at Xerox PARC (M for Model, V for View, C for Controller).
  204. Picture 2.3a Model-View-Controller Separation
  205. A Model is a store that contains data which should be presented visually, e.g. a text (sequence of characters plus font attributes), or a graph (set of graphical objects plus pen attributes), etc.
  206. A model is presented by a View. A view maps the model's contents into a rectangular display area, using frames as mappers to ports (e.g. screen ports or printer ports). Frames are also the input channels for mouse and keyboard actions.
  207. Several views may present the same model simultaneously, e.g. there may be two views presenting different parts of the same text, or a list of numbers may be shown as a table and as a bar chart simultaneously.
  208. Views are extended stores, and can thus be embedded in other stores, e.g. other views, or in models. The root of such a hierarchy is called a document. A document corresponds to a file, and is the root object displayed in a window.
  209. A view may also perform user interaction. However, complex applications delegate this task to another object called a Controller. A controller may further delegate the actual operation to an operation, which is an object that specifies an invertable operation on a view or its model, i.e. it supports the undo feature.
  210. Picture 2.3b  Document Example
  211. The example above shows the situation where two windows display a document with a text view, where the text contained in this view contains a graphic view. One of the windows is the main window, the other a child window of the same document. Child windows show all or part of a document's view hierarchy. The topmost view in a window is independent of its corresponding views in other windows, their size, scroll position, and other view attributes may differ. They only share the same model.
  212. As a consequence, if this model contains a view, the view is shared by all views (each in its own window) displaying the same model. However, for each window there exists one frame on this shared view. Thus there may be as many frames on any view as there are windows on this document.
  213. The outlined scheme has the effect that a document is a store hierarchy (not necessarily a tree, but a DAG, i.e. a directed acyclic graph), and that a window is a frame hierarchy (always a tree) which mirrors a subset of the store hierarchy. There are as many frame trees for a store hierarchy as there are windows displaying the same document.
  214. To summarize:
  215. - Store    base type of all storable objects
  216. - Model    data representation
  217. - View    data presentation
  218. - Controller    interaction
  219. - Frame    user input / display output mapper
  220. 2.4 Messages
  221. One of the most fundamental language constructs of Oberon/L are procedures. A procedure combines several statements into one more powerful entity, which can be used as a statement itself, e.g. to form even more powerful procedures.
  222. In order to support object-oriented programming, procedures may be called indirectly via an object. This indirection leads to different actual procedures being called, depending on the object's dynamic type. Procedures which behave in such a polymorphic way are called type-bound procedures (or methods).
  223. With any collection of similar procedures, it is theoretically possible to combine them into one procedure with an additional parameter. This parameter tells which member of the collection is selected when the procedure is called. As an example, consider the following procedures:
  224. PROCEDURE Show
  225. PROCEDURE Hide
  226. These procedures can be combined into one procedure
  227. PROCEDURE Handle (show: BOOLEAN)
  228. This procedure internally selects a Show or Hide behavior based on the additional parameter.
  229. Such a combination becomes problematic, however, if the parameter lists of the different procedures are different, e.g. if the above procedure should be combined with
  230. PROCEDURE Select (from, to: LONGINT)
  231. A solution to this problem is to pass a record as parameter to the combined procedure. Records are extensible, thus all necessary parameters can be combined in a suitable record extension:
  232.     Message = RECORD END;
  233.     ShowMsg = RECORD (Message) END;
  234.     HideMsg = RECORD (Message) END;
  235.     SelectMsg = RECORD (Message) from, to: LONGINT END;
  236. Such a record can then be passed to a general handler procedure, e.g. a type-bound procedure as in the example below:
  237. PROCEDURE (obj: Object) Handle (VAR msg: Message)
  238. This procedure can not only replace the procedures
  239. PROCEDURE (obj: Object) Show
  240. PROCEDURE (obj: Object) Hide
  241. PROCEDURE (obj: Object) Select (from, to: LONGINT)
  242. but also any other procedure bound to type Object. Internally, Handle uses type tests to determine the action to be taken, and type guards to access the particular parameters (i.e. the record fields of msg).
  243. A universal handler procedure is a simple and very general construct, but inconvenient and error-prone. The signature of a handler procedure reveals very little about what the procedure really does, and the compiler cannot tell if message record fields have not been set up correctly. Thus, Oberon/F generally uses distinct procedures for distinct operations.
  244. However, handler procedures can be convenient under special circumstances, namely when a procedure call must be applied to a large number of objects (broadcast of a message), or when the called object lets some other object do the work for it (forwarding of a message).
  245. In these cases, the number of normal procedures would have to be multiplied, e.g. there would have to be a BroadcastShow procedure in addition to the Show procedure, a BroadcastHide procedure in addition to the Hide procedure, etc. This is inconvenient, because it results in bloated interfaces, and because broadcast procedures typically all work exactly the same way internally, i.e. one Broadcast procedure should be sufficient in principle.
  246. For these reasons, the concept of universal handlers has been used in Oberon/F where this was most appropriate, i.e. where broadcasting or forwarding are used extensively. In the following paragraphs, these places are introduced.
  247. When a user types a key, presses a mouse button, or executes a menu command, these events must be communicated to the appropriate view. Such a view is called a focus view. Views are contained in documents, and documents are displayed in windows. In most user interfaces, one of these windows is the front window (i.e. the focus window), and interactions occur with this window. A window can contain a whole hierarchy of views, thus one of them must be defined as focus.
  248. Events like the ones described above are communicated by sending appropriate controller messages to the focus view (i.e. edit messages, scroll messages, etc.). Theses messages are not sent directly to the focus view, but are passed through the whole view hierarchy until they reach the focus. This makes it possible for a view to filter out (or to perform some other modification on) a message when desired, before it is passed to one of the embedded views.
  249. In fact, Oberon/F does not even know which view is currently the focus. Instead, it sends messages to the focus window's document, from where it is forwarded along the focus path until it reaches the focus view. Every view which receives a controller message can decide on its own whether it wants to forward the message to one of its embedded views, or whether it wants to interpret the message itself. In the latter case, it is the focus view by definition!
  250. Controller messages are forwarded throughout a hierarchy of views, thus they are appropriate candidates for a general forward procedure and for a handler procedure as outlined earlier.
  251. The focus view either handles a controller message itself, or it sends it to a controller object for this purpose. If the message's type is not known, it should simply be ignored, in order to allow for future extensions.
  252. Since in Oberon/F the same document can be shown in several windows simultaneously, every view may be visible several times simultaneously. Thus it is more precise to speak about the focus frame, instead of the focus view. Accordingly, a focus message is sent along the focus window's frame tree, instead of directly along the document's view hierarchy.
  253. Although most interactions are performed with the front window, this is not always the case. Sometimes, two windows are involved in an interaction: a dialog and a document window. As an example, the document window may contain a text view, while a "Find & Replace" dialog may lie in front of the document window. In this case, typing is routed to the dialog, while the find and replace commands operate on the document window.
  254. To support such a situation, Oberon/F defines two foci: a target focus (in the document window) and a front focus (in the dialog box). Every controller message is sent to exactly one of them.
  255. Picture 2.4a  Simplified Example of Focus Hiearchy
  256. When a controller message has arrived at its focus view, it may cause some effect there. A paste message may cause the clipboard's contents to be inserted into the focus view's model, for example. Afterwards, all views which display this same model must be updated, such that they show the new situation correctly. Oberon/F realizes this change propagation by sending a so-called model message to all affected views. This is an example of a message broadcast, and thus the second place where a general message handler is used in Oberon/F, in this case a handler for model messages. Model messages are not forwarded along a specific frame path, but rather sent to all affected views, using a Broadcast procedure.
  257. Unfortunately, there may not only be several views for the same model, but also several frames for the same view, because several windows may be open simultaneously on the same document. This requires that after a model modification, the change propagation must be performed in two steps: from the model to each affected view, and then to each affected frame. This is realized with a second broadcast mechanism, this time for so-called view messages.
  258. Picture 2.4b  Concept of Two-Level Broadcast
  259. All in all, there are only a few areas where universal handler procedures and extensible message records are used in Oberon/F, otherwise type-bound procedures are applied.
  260. TextControllers.StdCtrlDesc
  261. TextControllers.ControllerDesc
  262. Containers.ControllerDesc
  263. Controllers.ControllerDesc
  264. Geneva
  265. Documents.ControllerDesc
  266.